
#include "posix_fsm.h"

//================================================变量声明=======================================================//

//================================================函数声明=======================================================//
/**
 * @brief 	获取当前状态
 * @param 	fsm   : 状态机句柄
 *			state : 当前状态
 * @retval	详见 fsm_result 枚举
 * @note	\
 */
fsm_result fsm_state_get(fsm_t *fsm, int *state)
{
	if (!pthread_mutex_lock(&fsm->mutex))
		return FSM_VIE_LOCK;
	
	*state = fsm->state;
	pthread_mutex_unlock(&fsm->mutex);
	return FSM_RT_OK;
}

/**
 * @brief 	切换当前状态
 * @param 	fsm   : 状态机句柄
 *			state : 期望状态
 * @retval	详见 fsm_result 枚举
 * @note	\
 */
fsm_result fsm_state_set(fsm_t *fsm, int state)
{
	if (!pthread_mutex_lock(&fsm->mutex))
		return FSM_VIE_LOCK;
	
	fsm->state = state;
	pthread_mutex_unlock(&fsm->mutex);
	return FSM_RT_OK;
}

/**
 * @brief 	通过该方法获取在当前状态下, 指定事件到来时的对应动作处理回调
 * @param 	fsm   		 : 状态机句柄
 *			event 		 : 触发事件
 *			fsm_event_cb : 动作执行回调
 * @retval	详见 fsm_result 枚举
 * @note	/
 */
fsm_result fsm_event_handler_get(fsm_t *fsm, int event, fsm_event_cb *action)
{
	unsigned int i = 0;
	*action = NULL;
	
	if (!pthread_mutex_lock(&fsm->mutex))
		return FSM_VIE_LOCK;

	for (i = 0; i < fsm->table_num; ++i)
	{
		if (fsm->state == fsm->table[i].cur_state && event == fsm->table[i].trigger_event)
		{
			*action = fsm->table[i].do_action;
			break;
		}
	}
	pthread_mutex_unlock(&fsm->mutex);
	return (i < fsm->table_num) ? FSM_RT_OK : FSM_GO_TRAP;
}

/**
 * @brief 	当指定事件触发时, 状态机会自动寻找并调用对应的动作处理回调, 从而完成状态转移
 * @param 	fsm   : 状态机句柄
 *			event : 触发事件
 *			data  : 事件参数
 * @retval	详见 fsm_result 枚举
 * @note	/
 */
fsm_result fsm_event_exec(fsm_t *fsm, int event, void *data)
{
	unsigned int i = 0;

	if (!pthread_mutex_lock(&fsm->mutex))
		return FSM_VIE_LOCK;

	for (i = 0; i < fsm->table_num; ++i)
	{
		if (fsm->state == fsm->table[i].cur_state && event == fsm->table[i].trigger_event)
		{
			int transfer_state = fsm->table[i].next_state;
			if (fsm->table[i].do_action != NULL) 
			{
				transfer_state = fsm->table[i].do_action(data); //动作执行
			}
			//printf("change state [%d] -> [%d]\n", fsm->state, fsm->table[i].next_state);
			fsm->state = transfer_state;
			break;
		}
	}
	pthread_mutex_unlock(&fsm->mutex);
	return (i < fsm->table_num) ? FSM_RT_OK : FSM_GO_TRAP;
}
